<template>
  <div id="global-uploader" class="uploadDiv2">
    <uploader
      ref="uploader"
      :options="uploadOptions"
      :autoStart="false"
      :files="files"
      :file-status-text="statusText"
      @file-added="onFileAdded"
      @file-complete="onFileComplete"
      @file-success="onFileSuccess"
      @file-error="onFileError"
      class="uploader-app"
    >
      <uploader-unsupport></uploader-unsupport>
      <uploader-btn id="global-uploader-btn" :attrs="attrs" ref="uploadBtn">
        <i class="el-icon-upload2"></i>
        <span >上传文件</span>
      </uploader-btn>
      <uploader-list v-show="panelShow">
        <div class="file-panel" slot-scope="props" :class="{'collapse': collapse}" style="overflow: hidden;">
          <div class="file-title">
            <label>文件列表</label>
            <div class="operate">
              <el-button @click="fileListShow" type="text" :title="collapse ? '展开':'折叠' ">
                <i :class="collapse ? 'el-icon-plus': 'el-icon-minus'"></i>
              </el-button>
              <el-button @click="close" type="text" title="关闭">
                <i class="el-icon-close"></i>
              </el-button>
            </div>
          </div>
          <ul ref="fileList" class="file-list">
            <li v-for="file in props.fileList" :key="file.id" >
              <uploader-file :class="'file_' + file.id" :file="file" :list="true" ></uploader-file>
            </li>
            <div class="no-file" v-if="!props.fileList.length"><i class="iconfont icon-empty-file"></i> 暂无待上传文件</div>
          </ul>
        </div>
      </uploader-list>
    </uploader>
  </div>
</template>

<script>
import { merge } from "@/api/upload";
import $ from "jquery"
import SparkMD5 from 'spark-md5'
/* eslint-disable */
export default {
  name: "vue-uploader",
  props: {
    target: {
      type: String,
      default: "temp"
    }
  },
  data() {
    return {
      fileLength: 0,
      successLength: 0,
      files: [],
      statusText: {
        success: '上传成功',
        error: '出错了',
        uploading: '上传中',
        paused: '暂停中',
        waiting: '等待中'
      },
      uploadOptions: {
        // target: "http://59.77.233.200:5556/upload/chunk", // 本地区别
        // target: "http://121.40.129.104:5556/upload/chunk", // 本地区别
        target: "", // 本地区别
        chunkSize: 2 * 1024 * 1024,
        testChunks: true,
        simultaneousUploads: 1,
        checkChunkUploadedByResponse: function(chunk, message) {
          let objMessage = JSON.parse(message);
          // console.log('check')
          let chunkNumbers = objMessage.chunkNumbers;
          return (chunkNumbers || []).indexOf(chunk.offset + 1) >= 0;
        },
        headers: {},
        query() {},
        categoryMap: {
          image: ['gif', 'jpg', 'jpeg', 'png', 'bmp', 'webp'],
          Rar: ['rar','7z','zip','']
          // video: ['mp4', 'm3u8', 'rmvb', 'avi', 'swf', '3gp', 'mkv', 'flv'],
          // audio: ['mp3', 'wav', 'wma', 'ogg', 'aac', 'flac'],
          // document: ['doc', 'txt', 'docx', 'pages', 'epub', 'pdf', 'numbers', 'csv', 'xls', 'xlsx', 'keynote', 'ppt', 'pptx']
        }
      },
      attrs: {},
      panelShow: false, //选择文件后，展示上传panel
      collapse: false,
    };
  },
  created() {
    console.log("获取process.env.VUE_APP_FLASK_API",process.env.VUE_APP_FLASK_API)
    this.uploadOptions.target = process.env.VUE_APP_FLASK_API + "/upload/chunk"
  },
  methods: {
    onFileComplete() {
      // console.log("merge")
      var file = arguments[0].file
      // 很奇怪，这里直接file.uniqueIdentifier 获得的是undefined
      // console.log('uni:', arguments[0].uniqueIdentifier)
      const formData = new FormData();
      this.statusSet(file.id, 'merging');
      formData.append("identifier", arguments[0].uniqueIdentifier);
      formData.append("filename", file.name);
      formData.append("target", this.target);
      merge(formData).then(response => {
        console.log("上传文件",formData)
        this.statusRemove(file.id);
        this.$emit('onSuccess') // 子组件向父组件传值
      });

    },
    fileLen(){
      this.fileLength =this.fileLength+1
    },
    onFileAdded(file) {
      this.successLength = 0

      this.panelShow = true
      this.computeMD5(file);
      this.fileLen()
    },
    onFileSuccess(rootFile, file, response, chunk){
      this.successLength = this.successLength + 1

      if(this.successLength == this.fileLength){
        this.$message({
          message:"全部文件上传成功",
          type: "success"
        })
        this.fileLength = 0
      }

    },
    onFileError(rootFile, file, response, chunk) {
      this.$message({
        message: response,
        type: "error"
      });
    },
    close() {
      // this.uploader.cancel();
      const uploaderInstance = this.$refs.uploader.uploader
      uploaderInstance.cancel()
      this.panelShow = false;
    },
    fileListShow() {
      let $list = $('.file-panel .file-list');

      if ($list.is(':visible')) {
        $list.slideUp();
        this.collapse = true;
      } else {
        $list.slideDown();
        this.collapse = false;
      }
    },
    computeMD5(file) {
      let fileReader = new FileReader();
      let time = new Date().getTime();
      //这里需要用到File的slice( )方法，以下是兼容写法
      let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
      let currentChunk = 0;
      const chunkSize = 2 * 1024 * 1000;
      let chunks = Math.ceil(file.size / chunkSize);
      let spark = new SparkMD5.ArrayBuffer();
      // 文件状态设为"计算MD5"
      this.statusSet(file.id, 'md5');
      file.pause();

      loadNext();

      // FileReader的load事件，当文件读取完毕时触发
      fileReader.onload = (e => {
        spark.append(e.target.result);  // e.target指向上面的fileReader实例
        currentChunk++
        // 实时展示MD5的计算进度
        this.$nextTick(() => {
          $(`.myStatus_${file.id}`).text('校验MD5 '+ ((currentChunk/chunks)*100).toFixed(0)+'%')
        })
        if (currentChunk < chunks) {
          loadNext();
        } else {
          let md5 = spark.end();
          this.computeMD5Success(md5, file);
          // console.log(`MD5计算完毕：${file.name} \nMD5：${md5} \n分片：${chunks} 大小:${file.size} 用时：${new Date().getTime() - time} ms`);
        }
      });

      fileReader.onerror = function () {
        this.error(`文件${file.name}读取出错，请检查该文件`)
        file.cancel();
      };

      function loadNext() {
        // 分片读取文件
        let start = currentChunk * chunkSize;
        let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
        fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));  // 通过fileReader读取文件二进制码
      }
    },
    computeMD5Success(md5, file) {
      // 将自定义参数直接加载uploader实例的opts上
      // Object.assign(this.uploader.opts, {
      //     query: {
      //         ...this.params,
      //     }
      // })

      file.uniqueIdentifier = md5;
      file.resume();
      this.statusRemove(file.id);
    },
    statusRemove(id) {
      this.$nextTick(() => {
        $(`.myStatus_${id}`).remove();
      })
    },
    statusSet(id, status) {
      let statusMap = {
        md5: {
          text: '校验MD5',
          bgc: '#fff'
        },
        merging: {
          text: '合并中',
          bgc: '#ecf5ff'
        },
        transcoding: {
          text: '转码中',
          bgc: '#ecf5ff'
        },
        failed: {
          text: '上传失败',
          bgc: '#ecf5ff'
        }
      }
      this.$nextTick(() => {
        $(`<p class="myStatus_${id}"></p>`).appendTo(`.file_${id} .uploader-file-status`).css({
          'position': 'absolute',
          'margin': '0',
          'top': '0',
          'left': '-10px',
          'right': '0',
          'bottom': '0',
          'zIndex': '1000',
          'font-size': '14px',
          'background-color': statusMap[status].bgc
        }).text(statusMap[status].text)
      })
    }
  }
};
</script>
<style scoped lang="scss">
#global-uploader {
  display: inline-block !important;
  // position: fixed;
  z-index: 20;
  // right: 15px;
  // bottom: 15px;

  .uploader-app {
    // width: 200px;
  }

  .file-panel {
    position: fixed;
    right: 10px;
    bottom: 10px;
    width: 708px;
    background-color: #fff;
    border: 1px solid #e2e2e2;
    border-radius: 7px 7px 0 0;
    box-shadow: 0 0 10px rgba(0, 0, 0, .2);
    z-index: 10;

    .file-title {
      display: flex;
      height: 40px;
      line-height: 40px;
      padding: 0 15px;
      border-bottom: 1px solid #ddd;

      .operate {
        flex: 1;
        text-align: right;
      }
    }

    .file-list {
      position: relative;
      list-style: none;
      // padding-right:40px;
      text-align: left;
      height: 240px;
      overflow-x: hidden;
      overflow-y: auto;
      background-color: #fff;

      > li {
        background-color: #fff;
      }
    }

    &.collapse {
      .file-title {
        background-color: #E7ECF2;
      }
    }
  }

  .no-file {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 16px;
  }

  // /deep/.uploader-file-icon {
  //     // &:before {
  //     //     content: '' !important;
  //     // }

  //     // &[icon=image] {
  //     //     background: url(../../images/image-icon.png);
  //     // }
  //     // &[icon=video] {
  //     //     background: url(../../images/video-icon.png);
  //     // }
  //     // &[icon=document] {
  //     //     background: url(../../images/text-icon.png);
  //     // }
  //     // &[icon=zip] {
  //     //     background: url(../../images/file.png);
  //     // }
  //     // &[icon=audio]::before {
  //     //     background: url(../../images/music-icon-2.png);
  //     // }

  // }

  ///deep/.uploader-file-actions > span {
  //  margin-right: 6px;
  //}
}

#global-uploader-btn {
  width: 96px;
  height: 30px;
  color: #409EFF;
  background: #ecf5ff;
  border-color: #b3d8ff;
  font-size: 12px;
  padding: 6px 11px;
  border: 1px solid #DCDFE6
}

#global-uploader-btn:hover {
  background-color: #409EFF;
  color: #ecf5ff;
}
#global-uploader-btn>span {
  margin-left: 5px;
}
</style>
